#ifndef _AGORA_VIEWER_H
#define _AGORA_VIEWER_H

#if defined(_WIN32) || defined(_WIN64)
	#include <Windows.h>
	#include <conio.h>
#else
	#include <unistd.h>
	#include <stdlib.h>
	#include <string.h>
	#include <pthread.h>
	#include <termios.h>
#endif

#include <stdio.h>

#define VIEWER_CONSOLE_MODE		true

#include "Menu.h"

class Viewer{
private:
  
#if defined(_WIN32) || defined(_WIN64)
	CRITICAL_SECTION locker;
	HANDLE hMenu;
	HANDLE hMenuUnlock;
#else
	pthread_mutex_t locker;
	pthread_t hMenu;
	pthread_t hMenuUnlock;
#endif

public:
	void lock();
	void unlock();
	void wait();

	Viewer();
	
	int print(char *format, ...);
	int printn(char *format, ...);

	// ----------------------- //
	// ----- NO CALLBACK ----- //
	// ----------------------- //
	int inputc(bool blocking = true);
	char *input();

#if defined(_WIN32) || defined(_WIN64)
	template <class T, typename Q, typename R>
	void displayMainMenu(Menu<T, Q, R> *m){
		this->lock();
		this->unlock();

		ResetEvent(hMenu);

		HANDLE hThread = NULL;
		if(WaitForSingleObject(hMenuUnlock, 0) != WAIT_OBJECT_0){
			printf("\n --- Main Menu ---\n");
			m->show(false);
			
			hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)menuInput, 0, 0, 0);		
			while(WaitForSingleObject(hThread, 0) != WAIT_OBJECT_0){
				if(WaitForSingleObject(hMenuUnlock, 0) == WAIT_OBJECT_0){
					
					keybd_event('0', 0x45, 0, 0);
					keybd_event('0', 0x45, KEYEVENTF_KEYUP, 0);

					TerminateThread(hThread, 0);
					break;
				}

				Sleep(100);
			}

			DWORD v = 0;
			GetExitCodeThread(hThread, &v);
					
			SetEvent(hMenu);
			m->select((int)(v - '0'));

			Sleep(100);
		}

		ResetEvent(hMenuUnlock);
	};
#else
	template <class T, typename Q, typename R>
	void displayMainMenu(Menu<T, Q, R> *m){
		this->print("Not supported yet\n");
	}
	
	static int getch( )
	{
		struct termios oldt, newt;
		int ch;
		tcgetattr( STDIN_FILENO, &oldt );
		newt = oldt;
		newt.c_lflag &= ~( ICANON | ECHO );
		tcsetattr( STDIN_FILENO, TCSANOW, &newt );
		ch = getchar();
		tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
		return ch;
	}
#endif

	static int menuInput(){
		int v = getch();
		printf("%c\n", v);
		return v;
	};
};

#endif

